Week 4 Progress


This is the last week of our project, and we are giving ourselves a final push to complete as much as possible to achieve our goal. This week we have mainly worked on writing scripts, creating an interface, decorating the robot and adding the keyboard and mouse control. For this week, we have both contributed again and split the tasks into two. The decorating of the arm was designed by both team members, and then the coding parts had to be split in two.

We have decided that Dean would write the scripts that would be used for controlling the arm, and Thibault would be doing the Interface and keyboard and mouse controlling by calling each script. He also reviewed some Urbi functions like the record function are the demo one. Each member's task is very challenging because it requires quite a lot of work and time in order to complete our goal. To create the scripts we have designed two scripts, a recorder and a player, which help us to manually move the arm which would record the positions of each servo every 0,01 seconds, and store them into a file. The player script works by loading the recorded file and play each position for each servo every 0,01 seconds as well. These two scripts allow us to manually do human like movements of the arm and play them to demonstrate that our arm can indeed copy the human arm movements. A very important thing that we have done for the player script is to set the constraints (boundaries) for each servo. This part is very important because if we go outside the boundaries while recording the script, the player script would only read the values that are outside within range and ignore all the values that are outside our limits.

The other scripts that we are writing is that so when a button is clicked on the interface, it will send a signal to the Urbi IDE and execute that specific script. We are also writing scripts that will allow us to control the arm by using the keyboard and it works in a similar way to the mouse clicking, but instead it will send a signal once a button is pressed and execute that particular script. The keyboard will be used to manually control the arm in every direction and the mouse will be used to record a script, or play already recorded scripts which would give a different kind of interaction with the robotic arm.

We did not think a lot about the housing but when the time went to create it, we had to come up with an idea. We did not use the idea of the balloons because we where not sure at all of the result it could produce. The second idea was to use some plastic bottles. But Thibault thought that using some baby clothes would be nice and would even create a body for the robot. That is why we bought a nice baby hoodie and dressed up the arm and its support with it. Because the body was a bit flat, we decided to add a plastic head. The dressing of the robotic arm made the project much more enjoyable and fun to watch. The biggest surprise for us was that once we execute commands using the decorated robotic arm, the feeling and the look of the arm seem to be very realistic which can be pretty creepy at times. Below we will provide some pictures and scripts that we have done for this week. We will close the wiki with another page called Summary which would contain the presentation videos, the complete code and what we have achieved for this project and how we have done it.

To interact with Urbi easily without having to know the commands, we created a graphical interface. The main problem was to make an external program, graphical or not, interact with the Urbi server. We started by looking into the Java documentation and found javax.comm which allows to communicate with a serial port. But then we realised that we did not want to interact directly with the motors but rather with Urbi, so this solution was pointless. We discovered then another solution to establish the communication between the two programs. Because Urbi is a server, we would use a socket connection and send messages through this connection. The C++ function to send a message was not too complicated to create as there are plenty of examples on Internet. We establish a connection on the ip adress "127.0.0.1" and port "5353". What was difficult to figure out was to know how to receive them on Urbi because just sending a message does not trigger any process in the server. It appeared that the server needed to constantly listen to the port "5353". Then the question of the type of messages to send was asked because we tried to send urbi commands but nothing was happening. We found the solution of sending a string and creating a function in the Urbi script which looks at the content of the string and react in consequence. Each time a message is sent to Urbi, a connection is established.
Once the communication was established, we needed to create the interface. As it is not a main part of the project but rather a tool, we looked for an easy and fast way to develop it. We finally chose to use the library Qt, mostly because Thibault knew it from previous projects and because of the availability of Qt designer which allows to create graphically an interface. Qt also allows to trigger any input device like a keyboard, a mouse, or a joystick it solved in the same time the problem of the interaction with the software. The problem of the interface was solved.
DSC_0001.JPG


DSC_0010.JPG

Below we will provide some functions that we have created, and in the summary page we will provide the complete code that we have used.

This function is one of our most important functions because it is used before every recording made. This function allows us to unlock any servo that has been locked. the reason it is so important is because without unlocking the servos, we won't be able to move them
to manually do a recording.
function unlock()
{
this.shoulderRot.load = 0;
this.elbow.load = 0;
this.shoulder2.load = 0;
this.shoulder1.load = 0;
};

A basic function used to test if the shoulder moves to its upper position and back to its initial position. It's only used for
testing purposes.
function simpleMovement2()
{
var delay = 0.1;
this.shoulder1.targetPos = this.shoulder1.upperPos;
sleep(delay);
this.shoulder2.targetPos = this.shoulder2.iniPos;
};

Another basic function to test if servo A moves up, servo C goes to its maximum position, and servo D moves to the lower position.
Only used for testing.
function simpleMovement3()
{
var delay = 0.1;
this.shoulder1.targetPos = this.shoulder1.upperPos;
sleep(delay);
this.shoulderRot.targetPos = this.shoulderRot.maxLeft;
sleep(delay);
this.elbow.targetPos = this.elbow.lowerPos;
};

This is the record function used to record the moves made manually. It first resets each servo to its initial position by calling the reset
function. It then creates a variable o1 that creates a text file called output.txt and then a loop that stores the current positions of
each servo every 0.02 seconds. As you can see, it separates each servos value with a comma and after all four servos have their position
recorded it creates a new line.
function record()
{
reset();
var o1 = OutputStream.new(File.create("output.txt"));
every(0.03)
{
o1 << this.shoulder1.position << "," << this.shoulder2.position << "," this.shoulderRot.position << "," << this.elbow.position << "\n"
};
};
};

This is the reset play function that plays the record script. The function first executes the reset function to put every servo in its
initial state and then waits 1 second before loading the rest of function. We create a new variable called "is" that is used to load the
recorded file output.txt. We then create a new variable "line" that is used to get each line for the input stream "is". Then it has an if
condition that stops reading the file if the file has reached an ending. We then use echo to print every line that has been read, and
create a new variable ns which is used as an array that stores the the current line number and separates each position with the comma. We
then say that the first cell of the array reads the first position for servo A, cell 2 for servo B and so on. Each position is also read
as a float which is defined after the ns variable with .asFloat();
function player()
{
reset;
sleep(1s);
var is = InputStream.new(File.new("output.txt"));
var line;
reading:every(0.01)
{
line = is.getLine.acceptVoid;
if (line.isVoid)
{
reading.stop();
};
echo(line);
var ns = line.split(",");
this.shoulder1.targetPos = ns[0].asFloat();
this.shoulder2.targetPos = ns[1].asFloat();
this.shoulderRot.targetPos = ns[2].asFloat();
this.elbow.targetPos = ns[3].asFloat();
};
};